package cn.jhz.learn.blog.test.impl;

import static java.util.stream.Collectors.toList;

import java.util.List;
import java.util.Optional;
import java.util.Set;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

import com.google.common.collect.Sets;

import cn.jhz.learn.blog.common.bean.SimpleEntry;
import cn.jhz.learn.blog.component.RequestHolder;
import cn.jhz.learn.blog.service.core.open.CategoryService;
import cn.jhz.learn.blog.service.core.open.file.FileService;
import cn.jhz.learn.blog.service.core.open.LabelService;
import cn.jhz.learn.blog.service.core.open.photo.PhotoService;
import cn.jhz.learn.blog.service.core.SubfieldService;
import cn.jhz.learn.blog.po.file.BlogFile;
import cn.jhz.learn.blog.dao.photo.BlogPhotoMapper;
import cn.jhz.learn.blog.po.photo.BlogPhoto;

@Validated
@Service("photoService")
public class PhotoServiceImpl implements PhotoService {

	private final LabelService labelService;
	private final CategoryService categoryService;
	private final SubfieldService subfieldService;
	private final FileService fileService;
	private final BlogPhotoMapper photoMapper;
	
	@Autowired
	public PhotoServiceImpl(LabelService labelService, CategoryService categoryService, SubfieldService subfieldService
							, FileService fileService, BlogPhotoMapper photoMapper) {
		this.labelService = labelService;
		this.categoryService = categoryService;
		this.subfieldService = subfieldService;
		this.fileService = fileService;
		this.photoMapper = photoMapper;
	}
	
	@Override
	public Optional<List<BlogPhoto>> batchPublishPhoto(@NotNull @Valid BlogPhoto photo,
												 @NotNull SimpleEntry<MultipartFile[], @NotNull Set<String>> filesAndLabels) {
		
		List<SimpleEntry<String, BlogFile>> filesAndNames;
		List<BlogPhoto> toAddPhotos;
		
		//TODO：检测photo
		checkInfo(photo);
		
		filesAndNames = fileService.batchUploadFiles(filesAndLabels.getKey().orElseThrow(ExceptionConstant.argumentFileIsNull))
										.orElseThrow(ExceptionConstant.argumentFileIsNull);
		
		toAddPhotos = filesAndNames.stream()
									.map(temp -> {
											BlogPhoto newPhoto = BlogPhoto.builder().build();
											BeanUtils.copyProperties(photo, newPhoto);
											newPhoto.setFileId(temp.getValue().map(BlogFile::getId).get());
											newPhoto.setTitle(temp.getKey().get());
											return newPhoto;
										})
									.collect(toList());
					
		photoMapper.batchInsertSelective(toAddPhotos);
		labelService.batchAddPhotosLabels(toAddPhotos, filesAndLabels.getValue().orElseGet(Sets::newHashSet));
		return Optional.ofNullable(toAddPhotos);
	}

	@Override
	public Optional<Set<Integer>> batchRecyclePhotoById(@NotNull Set<Integer> photoIdSet) {
		batchCheckExist(photoIdSet);
		photoMapper.batchUpdateStatusByIdSet(photoIdSet, (byte) 4);
		return Optional.ofNullable(photoIdSet);
	}

	@Override
	public Optional<Set<Integer>> batchRemovePhotoById(@NotNull Set<Integer> photoIdSet) {
		batchCheckExist(photoIdSet);
		photoMapper.batchUpdateStatusByIdSet(photoIdSet, (byte) 0);
		return Optional.ofNullable(photoIdSet);
	}

	@Override
	public Optional<List<BlogPhoto>> batchModifyPhoto(@NotNull BlogPhoto photo, @NotNull Set<Integer> photoIdSet,
													  Set<String> labelSet) {
		return batchModify(photo, photoIdSet, Optional.ofNullable(labelSet).orElseGet(Sets::newHashSet));
	}

	@Override
	public Optional<BlogPhoto> modifyPhoto(@NotNull BlogPhoto photo, Set<String> labelSet) {
		List<BlogPhoto> photos = batchModify(photo, Sets.newHashSet(photo.getId()),
				Optional.ofNullable(labelSet).orElseGet(Sets::newHashSet)).get();
		if(photos.isEmpty())
			return Optional.empty();
		else
			return Optional.ofNullable(photos.get(0));
	}

	@Override
	public Optional<BlogPhoto> findPhotoById(Integer photoId) {
		// TODO Auto-generated method stub
		return null;
	}

	private Optional<List<BlogPhoto>> batchModify(BlogPhoto photo , Set<Integer> idSet, Set<String> labelSet){
		List<BlogPhoto> toModifyPhoto;

		batchCheckExist(idSet);
		checkInfo(photo);

		toModifyPhoto = idSet.stream()
				.map(
						id ->{
							BlogPhoto temp = BlogPhoto.builder().build();
							BeanUtils.copyProperties(photo, temp);
							temp.setId(id);
							return temp;
						})
				.collect(toList());

		labelService.batchModifyPhotosLabels(idSet, labelSet);
		photoMapper.batchUpdateByPrimaryKeySelective(toModifyPhoto);

		return Optional.of(toModifyPhoto);
	}

	@Override
	public void checkExist(Integer photoId) {
		if(photoMapper.countExistByIdAndBlogId(photoId, RequestHolder.getCurrentUser().getId()) == 0)
			throw ExceptionConstant.paramPhotoIsNotExist.get();
	}

	private void batchCheckExist(Set<Integer> idSet){

	}

	private void checkInfo(BlogPhoto photo) {
		if(!categoryService.checkCategoryIsExistById(photo.getCategoryId()))
			throw ExceptionConstant.paramCategoryIsNotExist.get();

		if(!subfieldService.checkPhotoSubfieldIsExistById(photo.getId()))
			throw ExceptionConstant.paramSubfieldIsNotExist.get();
	}
	
	private void setDefaultValue(BlogPhoto photo) {
		photo.setCategoryId(null);
		photo.setSubfieldId(null);
		photo.setStatus((byte) 1);
		photo.setVisibility(null);
	}
	
}
